Home:ALL Converter>How to optimise data inputs for my UIPicker and UICollectionView programmatically Swift iOS

How to optimise data inputs for my UIPicker and UICollectionView programmatically Swift iOS

Ask Time:2020-11-18T21:29:47         Author:jason

Json Formatter

I am a total noob and learning iOS development programmatically and not with storyboards.

I have created two test controllers

  1. Uses a UIPicker to allow selection of a Job Role using the scroll wheel
  2. Uses a UICollectionView to all selection of a Job Role by tapping an Icon

I will probably use the UIPicker when a user registers and the UICollectionView to select a role to view its details as a Menu

I have created arrays in each controller to provide the required data for each

What I would like to do is be able to use a Data Model to hold eNums that hold the common data used by both.

I am not sure how to create arrays for my picker and collection views

I wanted to use enums as later on when a user has made a selection and I pass the output to my next controllers to act on I felt it would be good to do a switch on the selected item.

Appreciate any guidance and also if I am totally mad and going about it all wrong.

Cheers

JobRoleMenuViewController.swift

   import UIKit

private let reuseIdentifier = "Cell"

class JobRoleMenuViewController: UICollectionViewController {
    
    // MARK: - Properties
    
    var jobRoleLabel: [String] = [
        "Doctor",
        "Teacher",
        "Student",
        "Shop Keeper",
        "Fire Fighter",
        "I'm So Lucky!"
    ]
    
    var jobRoleImage: [UIImage] = [
        UIImage(named: "doctor")!,
        UIImage(named: "teacher")!,
        UIImage(named: "student")!,
        UIImage(named: "retailer")!,
        UIImage(named: "firefighter")!,
        UIImage(named: "astronaut")!
    ]
    
    // MARK: - Lifecycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.backgroundColor = .white
        self.collectionView.register(JobRoleCell.self, forCellWithReuseIdentifier: reuseIdentifier)
    }
    
    // MARK: -
    
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return jobRoleImage.count
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! JobRoleCell
        cell.categoryLabel.text = jobRoleLabel[indexPath.item]
        cell.categoryImage = jobRoleImage[indexPath.row]
        return cell
    }
    
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("DEBUG: Tapped cell at: \(indexPath.row)")
    }
}

// MARK: -

extension JobRoleMenuViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = (view.frame.width - 2) / 3
        return CGSize(width: width, height: width)
    }
}

}

JobRoleCell.swift

Please note: in the below code centerX and anchor are extensions I have created in Extensions.swfit so I can reuse across all code

import UIKit

class JobRoleCell: UICollectionViewCell {
    
    // MARK: - Properties
    
    var categoryImage: UIImage? {
        didSet {
            guard let categoryImage = categoryImage else { return }
            imageView.image = categoryImage
        }
    }
    
    let categoryLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 16)
        label.tintColor = .black
        return label
    }()
    
    let imageView: UIImageView = {
        let iv = UIImageView()
        return iv
    }()
    
    // MARK: - Lifcycle
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        addSubview(imageView)
        imageView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 40, paddingLeft: 40, paddingBottom: 40, paddingRight: 40)
        
        addSubview(categoryLabel)
        categoryLabel.centerX(inView: self)
        categoryLabel.anchor(bottom: bottomAnchor)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }    
}

JobRolePicker.swift

import UIKit

class JobRolePickerController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    
    // MARK: - Properties
    
    let jobRolePickerData: [String] = [
        "Doctor",
        "Teacher",
        "Student",
        "Shop Keeper",
        "Fire Fighter",
        "Astronaut"
    ]
    
    // MARK: - Lifecycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        let picker: UIPickerView = UIPickerView()
        picker.delegate = self as UIPickerViewDelegate
        picker.dataSource = self as UIPickerViewDataSource
        self.view.addSubview(picker)
        picker.center = self.view.center
    }
    
    // MARK: - PickerController
    
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return jobRolePickerData.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        let row = jobRolePickerData[row]
        return row
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        
        //        let jobRoleSelected = jobRolePickerData[pickerView.selectedRow(inComponent: 0)]
        print("DEBUG: Tapped cell at: \(jobRolePickerData[row])")
    }
}

I would like to try and use this to hold the data and share across all that need it and also use this to switch the outputs of both JobRoleMenuView and JobRolePickerView

Job.swift

import Foundation

enum JobRole: Int {
    //enum TradeType: CaseIterable {
    case doctor
    case teacher
    case student
    case retailer
    case fireFighter
    case astronaut
    
    var JobTitle: String {
        switch self {
        
        case .doctor:
            return "Doctor"
        case .teacher:
            return "Teacher"
        case .student:
            return "Student"
        case .retailer:
            return "Shop Keeper"
        case .fireFighter:
            return "Fire Fighter"
        case .astronaut:
            return "Fly me to the Moon"
        }
    }
    
    var JobImage: String? {
        switch self {
        
        case .doctor:
            return "doctor"
        case .teacher:
            return "teacher"
        case .student:
            return "student"
        case .retailer:
            return "retailer"
        case .fireFighter:
            return "firefighter"
        case .astronaut:
            return "astronaut"
        }
    }
}

I currently have the following screens and currently in debug window it prints out whatever is selected on each

JobRoleMenuScreenShot

JobRolePickerScreenShot

Author:jason,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/64894073/how-to-optimise-data-inputs-for-my-uipicker-and-uicollectionview-programmaticall
yy